package org.bwf.study.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.bwf.study.util.MD5;
import org.bwf.study.util.RedisUntil;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Aspect
@Component
@Slf4j
public class RedisOperation {
    @Resource
    private RedisUntil redisUntil;

    // ra 需要绑定自定义注解的占位符
    @Around(value = "@annotation(ra)")
    // ProceedingJoinPoint 这是AOP获取被拦截对象的所有信息
    public Object proceedAround(ProceedingJoinPoint joinPoint, RedisAnnotation ra){
        log.info("RedisOperation--proceeding......");
        // 获取被拦截方法的参数
        Object[] args = joinPoint.getArgs();
        // 设置Redis缓存的key
        // 有些方法有参数，有些方法没有参数
        // 先定义key值为方法的签名 org.bwf.study.service.impl.FilmQueryListDTO public FilmQueryListDTO FilmQueryList(FilmQueryListBO filmQueryListBO)
        String key = joinPoint.getSignature().toString();
        if(args.length > 0) key += args[0].toString(); // 如果有参数，key就是方法的签名加上第一个参数bo的toString字符串
        // key的MD5的格式化
        key = new MD5().md5(key);
        log.info("redis key:" + key);
        // 读取Redis
        Object redisResult = redisUntil.get(key);
        if(redisResult !=null){
            log.info("redis was read.......");
            return redisResult;
        }

        try {
            // redisResult = 被拦截方法的运行结果
            redisResult = joinPoint.proceed(args);
            // 这里的redisResult判断的是方法执行后返回值是否为空
            if(redisResult != null){
                log.info("redis was save......");
                // 在Redis中存放方法执行后的结果， ra.Duration就是自定义注解的属性
                redisUntil.set(key, redisResult, ra.Duration());
            }
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return redisResult;
    }
}
